package com.gitee.zycra.future.job.dao;

import com.gitee.zycra.future.job.common.model.JobNode;
import com.gitee.zycra.jdbc.common.BaseDao;
import com.gitee.zycra.jdbc.common.CommonSelector;
import com.gitee.zycra.jdbc.enums.SQLConditionEnum;
import com.gitee.zycra.jdbc.enums.SQLLinkEnum;
import com.gitee.zycra.jdbc.util.SQLBlock;
import com.gitee.zycra.jdbc.util.SQLChain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @author zycra
 */
@Repository
public class JobNodeDao extends BaseDao<JobNode> {

    @Autowired
    private CommonSelector commonSelector;

    /**
     * 插入
     *
     * @param jobNode 节点对象
     * @return 插入条数
     */
    public int insertJobNode(JobNode jobNode) {
        return insertIntoTable(jobNode);
    }

    /**
     * 更新节点信息
     *
     * @param jobNode 节点对象
     * @return 更新条数
     */
    public int updateJobNode(JobNode jobNode) {
        return updateTableById(jobNode, false);
    }

    /**
     * 将上次心跳时间超过1分钟的置为失效
     *
     * @return 影响行数
     */
    public int checkAliveAndUpdate() {
        return getJdbcTemplate().update("UPDATE job_node SET alive = 0 WHERE last_heart_beats_time < DATE_SUB(NOW(), INTERVAL 5 SECOND)");
    }

    /**
     * 查询节点信息
     *
     * @param applicationName 应用名称
     * @param nodeIp          节点IP
     * @return 查询结果
     */
    public List<JobNode> selectByApplicationAndIp(String applicationName, String nodeIp) {
        return selectTableByNotNullColumnEquals(new JobNode().setApplicationName(applicationName).setNodeIp(nodeIp), false);
    }

    /**
     * 根据节点ID查询
     *
     * @param nodeId 节点ID
     * @return 节点信息
     */
    public JobNode selectById(Long nodeId) {
        return selectTableById(new JobNode().setId(nodeId));
    }

    /**
     * 根据应用查询适合分配的节点
     *
     * @param applicationName 应用名称
     * @param excludeIp       要排除的节点
     * @return 适合分配的节点
     */
    public String selectToDispatchNode(String applicationName, String excludeIp) {
        SQLChain sqlChain = SQLChain.builder()
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "alive", SQLConditionEnum.EQUALS, 1))
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "application_name", SQLConditionEnum.EQUALS, applicationName))
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "node_ip", SQLConditionEnum.NOT_EQUALS, excludeIp))
                .build();
        return commonSelector.selectOneByParam(getJdbcTemplate(),
                "SELECT node_ip FROM job_node" + sqlChain.getSQL() + " ORDER BY running_count, memory_used_ratio, cpu_used_ratio LIMIT 1",
                String.class, sqlChain.getParamList(), false);
    }
}
